#include "my_stdio.h"

static MyFILE *BuyFile(int fd, const char *mode)
{
    MyFILE *NewFile = (MyFILE *)malloc(sizeof(MyFILE));

    if (NewFile == NULL)
    {
        close(fd); // 防止文件描述符泄露
        return NULL;
    }

    NewFile->fileno = fd;
    NewFile->bufferlen = 0;
    memset(NewFile->outbuffer, 0, MAX);
    NewFile->flush_method = LINE_FLUSH; // 缓冲区大小应使用MAX而非未初始化的bufferlen
    return NewFile;
}

MyFILE *mfopen(const char *file_name, const char *mode)
{
    // 定义文件描述符
    int fd = -1;

    // 以读模式打开
    if (strcmp(mode, "r") == 0)
    {
        fd = open(file_name, O_RDWR);
    }

    // 以写模式打开
    else if (strcmp(mode, "w") == 0)
    {
        fd = open(file_name, O_CREAT | O_WRONLY | O_TRUNC, 0666);
    }
    // 以追加模式打开
    else if (strcmp(mode, "a") == 0)
    {
        fd = open(file_name, O_CREAT | O_WRONLY | O_APPEND, 0666);
    }

    if (fd < 0)
    {
        perror("mfopen fail");
        return NULL;
    }

    return BuyFile(fd, mode);
}

int mfwrite(MyFILE *stream, void *str, int len)
{
    // 先将写入的内容刷新到语言层缓冲区
    // 确保len不越界
    int free_space = MAX - stream->bufferlen;
    if (len > free_space)
    {
        len = free_space;
    }

    // 按字节长度拷贝
    memcpy(stream->outbuffer + stream->bufferlen, str, len);
    stream->bufferlen = stream->bufferlen + len;

    // 将其写入系统级缓冲区(仅考虑行缓冲)
    if ((stream->flush_method & LINE_FLUSH) && (stream->bufferlen > 0) && (stream->outbuffer[stream->bufferlen - 1] == '\n'))
        mfflush(stream);

    // 返回实际拷贝的字节数
    return len;
}

// 将语言层缓冲区数据刷新到系统级缓冲区
void mfflush(MyFILE *stream)
{
    if (stream->bufferlen > 0)
        // 进行写入
        write(stream->fileno, stream->outbuffer, stream->bufferlen);
    stream->bufferlen = 0;
}

void mfclose(MyFILE *stream)
{
    // 文件描述符必须大于0
    if (stream->fileno < 0)
        return;
    // 关闭文件前先把内容刷新到缓冲区
    mfflush(stream);
    // 调用close关闭
    close(stream->fileno);
    // 释放结点
    free(stream);
}
